package com.yorick.netty;

import com.yorick.netty.messageListener.Listener;
import com.yorick.netty.utils.ServerUtil;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.group.ChannelGroup;
import io.netty.channel.group.DefaultChannelGroup;
import io.netty.handler.timeout.IdleStateEvent;
import io.netty.util.concurrent.GlobalEventExecutor;
import lombok.extern.slf4j.Slf4j;

import javax.annotation.Resource;


/**
 * @author 陈治杰
 * @Title: EchoServerHandler
 * @Description: 自定义handler实现网络操作业务逻辑
 * @date 2021/7/1 17:32
 */
@ChannelHandler.Sharable
@Slf4j
public class EchoServerHandler extends ChannelInboundHandlerAdapter {
    Listener listener = new Listener();
    public static final ChannelGroup channels = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        channels.add(ctx.channel());
        log.info("{}:已经连接", ctx.channel().remoteAddress());
        log.info("当前共有{}个客户端连接", channels.size());
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        log.info("{}:已经断开", ctx.channel().remoteAddress());

    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        ByteBuf in = (ByteBuf) msg;
        byte[] data = new byte[2];
        in.readBytes(data);
        short msg_length = ServerUtil.byte2short(data);
        byte[] msg_id = new byte[4];
        in.readBytes(msg_id);
        int msg_id_int = ServerUtil.bytes2IntBig(msg_id);
        byte[] msg_body = new byte[msg_length];
        in.readBytes(msg_body);
        listener.getListener(msg_id_int,msg_body,ctx);
    }

    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
        // 将未处决消息冲刷到远程节点， 并且关闭该Channel
        ctx.writeAndFlush(Unpooled.EMPTY_BUFFER)
                .addListener(ChannelFutureListener.CLOSE_ON_FAILURE);
    }

    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
        IdleStateEvent event = (IdleStateEvent) evt;

        String eventType = null;

        switch (event.state()) {
            case READER_IDLE:
                eventType = "读空闲";
                break;
            case WRITER_IDLE:
                eventType = "写空闲";
                break;
            case ALL_IDLE:
                eventType = "读写空闲";
                break;
        }
        System.out.println();
        log.error("{}超时事件：{}", ctx.channel().remoteAddress(), eventType);
        ctx.channel().close();
    }

    /**
     * 异常处理
     *
     * @param ctx
     * @param cause
     * @throws Exception
     */
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        //打印异常栈跟踪
        log.error(cause.getMessage());
        // 关闭该Channel
        ctx.close();
    }

    public void channelSend(ChannelHandlerContext ctx, int msg, byte[] body) {
        byte[] s_data = new byte[body.length + 6];
        byte[] s_id = ServerUtil.intToByteArray(msg);
        byte[] s_length = ServerUtil.short2Byte((short) body.length);
        System.arraycopy(s_length, 0, s_data, 0, s_length.length);
        System.arraycopy(s_id, 0, s_data, 2, s_id.length);
        System.arraycopy(body, 0, s_data, 6, body.length);
        ByteBuf resp = Unpooled.copiedBuffer(s_data);
        ctx.write(resp);
    }

}